-
Notifications
You must be signed in to change notification settings - Fork 532
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable Synchronous Child Datastore Creation #22962
base: main
Are you sure you want to change the base?
Enable Synchronous Child Datastore Creation #22962
Conversation
…to prototype-sync-ds-create
…to prototype-sync-ds-create
…to prototype-sync-ds-create
…to prototype-sync-ds-create
…to prototype-sync-ds-create
cc8dd48
to
e19241d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Coverage Summary
↑ packages.runtime.container-runtime.src:
Line Coverage Change: 0.03% Branch Coverage Change: 0.04%
Metric Name | Baseline coverage | PR coverage | Coverage Diff |
---|---|---|---|
Branch Coverage | 92.90% | 92.94% | ↑ 0.04% |
Line Coverage | 94.50% | 94.53% | ↑ 0.03% |
Baseline commit: 54f2a18
Baseline build: 304086
Happy Coding!!
Code coverage comparison check passed!!
⯅ @fluid-example/bundle-size-tests: +3.46 KB
Baseline commit: 54f2a18 |
7c98ad0
to
24a7d4d
Compare
caf324e
to
908b467
Compare
@@ -523,6 +530,43 @@ export abstract class FluidDataStoreContext | |||
return factory; | |||
} | |||
|
|||
createChildDataStoreSync<T extends IFluidDataStoreFactory>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reasoning for:
- Putting this on FluidDataStoreContext instead of ContainerRuntime, given that ContainerRuntime currently has the async
createDataStore
? - Requiring it to be a child?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only the context has access to its factory synchronously, as its factory must be loaded before it is realized. This is basically the same pattern we use for dds.
* | ||
* @param childFactory - The factory of the datastore to be created. | ||
*/ | ||
createChildDataStoreSync?<T extends IFluidDataStoreFactory>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EDIT: I meant to put this comment in dataStoreFactory.ts, oops :)
I don't think I understand what the motivating scenario is for this PR, so I'd love to learn more about that. This comment is purely taking this PR at face value, so if I'm missing some special context let me know.
At a very high level, I'd question whether a sync factory pattern is moving in a good direction for our overall instantiation flows.
One pain point of Aqueduct (and therefore almost all of our current data store examples) is that the async startup flows are deferred to the data store instance (i.e. async initializingFirstTime
, async hasInitialized
). This leaves the instance in a prolonged "half-initialized" state which is prone to errors that don't account for certain invariants being violated.
Fluid basically mandates async somewhere in the construction flow though, due to retrieving handles, getChannel, etc.), so we can't go fully sync all the way to full initialization for most scenarios.
An alternative approach (ditching Aqueduct) would be to embrace an async factory, and move all async initialization up to the factory such that by the time we call the instance constructor, we are ready to be fully sync (and the instance is fully initialized in the constructor).
I've explored this pattern in https://github.com/microsoft/FluidFramework/blob/main/examples/utils/migration-tools/src/migrationTool.ts if you'd like an example. Fully admit there's some personal preference here, but I think this aligns better with DI principles, simplifies the instance class, and strengthens the instance class's invariants.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
scriptor has a case where they want to create a child datastore in response to user input, so there is no opportunity to do async actions.
i'd not confuse this with all instantiation, which include load, load must always be async. Create on the other hand can be synchronous, and that is what is enabled here. This matches how dds work.
We can't split the sync part and the async part here. the whole things need to be sync, as we need a net new datastore synchronously that ready to be used, and have its handle stores in the same js turn, to not break on user input.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, thank you - that makes more sense.
* @legacy | ||
* @alpha | ||
*/ | ||
export type NamedFluidDataStoreRegistryEntry2 = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
adding a new type is the most compatible thing according to our type tests, as it typescript has trouble with inference over typed arrays. not sure what to call this, everything else feels quite verbose, so kind of happy with just adding 2
@@ -3,7 +3,10 @@ | |||
* Licensed under the MIT License. | |||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i basically rewrote this test to split the parent and child datastore, and handle more cases, so i'd recommend split view, to really just review the latest.
🔗 No broken links found! ✅ Your attention to detail is admirable. linkcheck output
|
This change introduces a new pattern for datastore creation that is synchronous, specifically it allows the synchronous creation of a datastore from another datastore when the datastore being created is a child available synchronously via the existing datastore's registry, and the child's factory support synchronous creation. In addition to being synchronous, this method of datastore creation is also strongly typed for the consumer.